package com.itheima.book.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.apis.note.INoteClient;
import com.itheima.apis.review.IReviewClient;
import com.itheima.book.mapper.BookMapper;
import com.itheima.book.service.BookService;
import com.itheima.model.book.dtos.BookDto;
import com.itheima.model.book.pojos.Book;
import com.itheima.model.book.vos.BookVo;
import com.itheima.model.common.dtos.PageResponseResult;
import com.itheima.model.common.dtos.ResponseResult;
import com.itheima.model.common.enums.AppHttpCodeEnum;
import com.itheima.model.user.pojos.User;
import com.itheima.utils.thread.MpThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService {
    @Autowired
    private BookMapper bookMapper;
    @Autowired
    private INoteClient noteClient;
    @Autowired
    private IReviewClient reviewClient;
    /**
     * 根据分类Id获取图书列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getBookList(BookDto dto) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //校验参数
        dto.checkParam();
        //分页查询
        IPage<Book> page = bookMapper.getBookList(new Page<>(dto.getPage(), dto.getSize()), dto.getCategoryId());
        //结果返回
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
        responseResult.setData(page.getRecords());
        return responseResult;
    }

    /**
     * 获取用户书架的图书
     *
     * @return
     */
    @Override
    public ResponseResult getBookShelf() {
        User user = MpThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        List<Book> list = bookMapper.getBookShelf(user.getId());
        return ResponseResult.okResult(list);
    }

    /**
     * 添加图书到书架
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult addToBookShelf(Integer id) {
        User user = MpThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        bookMapper.addToBookShelf(user.getId(), id);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 从书架移除图书
     *
     * @param ids
     * @return
     */
    @Override
    public ResponseResult removeFromBookShelf(String[] ids) {
        User user = MpThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        bookMapper.removeFromBookShelf(user.getId(), ids);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 获取图书信息
     *
     * @param bookId
     * @return
     */
    @Override
    @Cacheable(value = "book", key = "#bookId")
    public ResponseResult getBookVo(Integer bookId) {
        Book book = getOne(Wrappers.<Book>lambdaQuery().eq(Book::getId, bookId));
        if (book == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        BookVo vo = new BookVo();
        BeanUtils.copyProperties(book, vo);
        //补充配置数据
        vo.setNoteCount(24);
        vo.setReadCount(54);
        vo.setReviewCount(65);
        return ResponseResult.okResult(vo);
    }

    /**
     * 获取用户图书笔记列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getUserBookNotes(BookDto dto) {
        User user = MpThreadLocalUtil.getUser();
        if (user == null || dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        dto.checkParam();
        ResponseResult noteResult = noteClient.countNotesByBookForUser(user.getId());
        if (!noteResult.getCode().equals(200)) {
            log.error("调用笔记服务失败，用户ID：{}", user.getId());
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "获取笔记统计失败");
        }
        // 解析笔记统计结果（Map<bookId, count>）
        String noteJSON = JSON.toJSONString(noteResult.getData());
        Map<Integer, Integer> bookNoteCountMap = JSON.parseObject(noteJSON, new com.alibaba.fastjson.TypeReference<Map<Integer, Integer>>() {});
        if (bookNoteCountMap == null || bookNoteCountMap.isEmpty()) {
            return ResponseResult.okResult(null); // 无数据时返回空结果
        }

        // 提取图书ID列表并分页
        List<Integer> bookIds = bookNoteCountMap.keySet().stream().collect(Collectors.toList());
        int page = dto.getPage();
        int size = dto.getSize();
        int total = bookIds.size();
        int start = (page - 1) * size;
        if (start >= total) {
            return new PageResponseResult(page, size, total);
        }
        int end = Math.min(start + size, total);
        List<Integer> pageBookIds = bookIds.subList(start, end);

        // 查询分页后的图书信息
        List<Book> books = bookMapper.selectBatchIds(pageBookIds);
        if (books == null || books.isEmpty()) {
            return new PageResponseResult(page, size, total);
        }

        // 转换为包含笔记数的VO
        List<BookVo> bookVos = books.stream().map(book -> {
            BookVo vo = new BookVo();
            BeanUtils.copyProperties(book, vo);
            vo.setNoteCount(bookNoteCountMap.get(book.getId()).intValue()); // 设置当前图书的笔记数
            // 补充其他统计字段（按需添加）
            setNullFields(vo);
            return vo;
        }).collect(Collectors.toList());

        // 封装分页结果
        PageResponseResult responseResult = new PageResponseResult(page, size, total);
        responseResult.setData(bookVos);
        return responseResult;
    }

    /**
     * 获取用户图书书评列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getUserBookReviews(BookDto dto) {
        User user = MpThreadLocalUtil.getUser();
        if (user == null || dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        dto.checkParam();
        ResponseResult reviewResult = reviewClient.countReviewsByBookForUser(user.getId());
        if (!reviewResult.getCode().equals(200)) {
            log.error("调用书评服务失败，用户ID：{}", user.getId());
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "获取书评统计失败");
        }
        // 解析笔记统计结果（Map<bookId, count>）
        String reviewJSON = JSON.toJSONString(reviewResult.getData());
        Map<Integer, Integer> bookReviewCountMap = JSON.parseObject(reviewJSON, new com.alibaba.fastjson.TypeReference<Map<Integer, Integer>>() {});
        if (bookReviewCountMap == null || bookReviewCountMap.isEmpty()) {
            return ResponseResult.okResult(null); // 无数据时返回空结果
        }

        // 提取图书ID列表并分页
        List<Integer> bookIds = bookReviewCountMap.keySet().stream().collect(Collectors.toList());
        int page = dto.getPage();
        int size = dto.getSize();
        int total = bookIds.size();
        int start = (page - 1) * size;
        if (start >= total) {
            return new PageResponseResult(page, size, total);
        }
        int end = Math.min(start + size, total);
        List<Integer> pageBookIds = bookIds.subList(start, end);

        // 查询分页后的图书信息
        List<Book> books = bookMapper.selectBatchIds(pageBookIds);
        if (books == null || books.isEmpty()) {
            return new PageResponseResult(page, size, total);
        }

        // 转换为包含笔记数的VO
        List<BookVo> bookVos = books.stream().map(book -> {
            BookVo vo = new BookVo();
            BeanUtils.copyProperties(book, vo);
            vo.setReviewCount(bookReviewCountMap.get(book.getId()).intValue()); // 设置当前图书的笔记数
            // 补充其他统计字段（按需添加）
            setNullFields(vo);
            return vo;
        }).collect(Collectors.toList());

        // 封装分页结果
        PageResponseResult responseResult = new PageResponseResult(page, size, total);
        responseResult.setData(bookVos);
        return responseResult;
    }

    /**
     * 清空一些字段
     * @param vo
     */
    private static void setNullFields(BookVo vo) {
        vo.setCategoryId(null);
        vo.setPublisher(null);
        vo.setDescription(null);
        vo.setUrl(null);
        vo.setCreateTime(null);
        vo.setUpdateTime(null);
    }

    /**
     * 根据分类ID获取图书列表（Feign专用）
     * @param categoryId
     * @param page
     * @param size
     * @return
     */
    @Override
    public ResponseResult getBooksByCategory(Integer categoryId, Integer page, Integer size) {
        if (categoryId == null || page == null || size == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        
        // 分页查询
        IPage<Book> bookPage = bookMapper.getBookList(new Page<>(page, size), categoryId);
        
        // 结果返回
        ResponseResult responseResult = new PageResponseResult(page, size, (int) bookPage.getTotal());
        responseResult.setData(bookPage.getRecords());
        return responseResult;
    }

    /**
     * 获取新书列表（Feign专用，按创建时间倒序）
     * @param page
     * @param size
     * @return
     */
    @Override
    @Cacheable(value = "newBooks", key = "#page + '_' + #size")
    public ResponseResult getNewBooks(Integer page, Integer size) {
        if (page == null || size == null) {
            page = 1;
            size = 10;
        }
        
        // 按创建时间倒序查询
        IPage<Book> bookPage = page(
            new Page<>(page, size),
            Wrappers.<Book>lambdaQuery()
                .orderByDesc(Book::getCreateTime)
        );
        
        // 结果返回
        ResponseResult responseResult = new PageResponseResult(page, size, (int) bookPage.getTotal());
        responseResult.setData(bookPage.getRecords());
        return responseResult;
    }
}
